import java.awt.Point;
import java.util.*;
import java.util.concurrent.TimeUnit;
import javax.swing.JLabel;

public class CommonUtils {
    // 卡牌尺寸和布局常量
    private static final int CARD_WIDTH = 71;
    private static final int CARD_HEIGHT = 96;
    private static final int PLAYER_HAND_SPACING = 15;  // 玩家手牌间距
    private static final int PLAYER_HAND_OFFSET = 21;   // 玩家手牌偏移量

    /**
     * 判断卡牌组合的牌型
     * @param cards 卡牌列表
     * @return 牌型枚举值
     */
    public static CardType judgeCardType(List<Card> cards) {
        if (cards == null || cards.isEmpty()) 
            return CardType.INVALID;
        
        // 获取卡牌数值并创建计数映射
        List<Integer> values = getCardValues(cards);
        Map<Integer, Integer> countMap = createCountMap(values);
        CardIndex cardIndex = createCardIndex(countMap);

        // 根据牌数确定牌型
        return determineCardType(cards.size(), cardIndex, values);
    }

    /**
     * 平滑移动组件动画效果
     * @param component 要移动的组件
     * @param from 起始位置
     * @param to 目标位置
     */
    public static void smoothMove(JLabel component, Point from, Point to) {
        if (from.x != to.x) {
            // 计算移动轨迹的线性方程参数
            double slope = (double)(to.y - from.y) / (to.x - from.x);
            double intercept = to.y - to.x * slope;
            int step = from.x < to.x ? 20 : -20;  // 移动方向
            
            // 逐帧移动组件
            for (int x = from.x; Math.abs(x - to.x) > 20; x += step) {
                int y = (int)(slope * x + intercept);
                component.setLocation(x, y);
                
                // 添加动画延迟
                try {
                    TimeUnit.MILLISECONDS.sleep(5);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
        // 最终定位到目标位置
        component.setLocation(to);
    }

    /**
     * 排序卡牌（从大到小）
     * @param cards 卡牌列表
     */
    public static void sortCards(List<Card> cards) {
        cards.sort((card1, card2) -> {
            String name1 = card1.getCardName();
            String name2 = card2.getCardName();
            
            // 解析花色和数值
            int suit1 = Integer.parseInt(name1.substring(0, 1));
            int suit2 = Integer.parseInt(name2.substring(0, 1));
            int value1 = getCardValue(card1);
            int value2 = getCardValue(card2);
            
            // 特殊牌处理（王、A、2）
            value1 = adjustSpecialCardValue(suit1, value1);
            value2 = adjustSpecialCardValue(suit2, value2);
            
            // 先比较数值，数值相同比较花色
            return value2 - value1 != 0 ? value2 - value1 : suit2 - suit1;
        });
    }

    /**
     * 获取卡牌数值（用于比较大小）
     * 数值映射：3-10→3-10, J-11, Q-12, K-13, A-14, 2-15, 小王-16, 大王-17
     * @param card 卡牌对象
     * @return 卡牌数值权重
     */
    private static int getCardValue(Card card) {
        String name = card.getCardName();
        // 卡牌名称格式："花色-数值" (如 "1-13" 表示黑桃K)
        String valuePart = name.substring(2);  // 获取数值部分
        
        // 特殊牌处理
        if ("1".equals(valuePart)) return 14;   // A
        if ("2".equals(valuePart)) return 15;   // 2
        if ("14".equals(valuePart)) return 16;  // 小王
        if ("15".equals(valuePart)) return 17;  // 大王
        
        return Integer.parseInt(valuePart);  // 普通牌3-13
    }
    
    /**
     * 调整特殊卡牌的数值权重
     * @param suit 花色（5表示王）
     * @param value 原始数值
     * @return 调整后的权重值
     */
    private static int adjustSpecialCardValue(int suit, int value) {
        // 王牌额外加权
        if (suit == 5) {
            return value + 100;  // 确保王牌最大
        }
        // A和2额外加权
        if (value == 14) return value + 20;  // A
        if (value == 15) return value + 30;  // 2
        return value;
    }

    /**
     * 获取卡牌数值列表
     * @param cards 卡牌列表
     * @return 数值列表
     */
    private static List<Integer> getCardValues(List<Card> cards) {
        List<Integer> values = new ArrayList<>();
        for (Card card : cards) {
            values.add(getCardValue(card));
        }
        return values;
    }

    /**
     * 创建卡牌数值计数映射
     * @param values 卡牌数值列表
     * @return 数值->出现次数的映射
     */
    private static Map<Integer, Integer> createCountMap(List<Integer> values) {
        Map<Integer, Integer> countMap = new HashMap<>();
        for (int value : values) {
            countMap.put(value, countMap.getOrDefault(value, 0) + 1);
        }
        return countMap;
    }

    /**
     * 创建卡牌索引（按重复次数分组）
     * @param countMap 计数映射
     * @return 卡牌索引对象
     */
    private static CardIndex createCardIndex(Map<Integer, Integer> countMap) {
        CardIndex cardIndex = new CardIndex();
        for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
            int value = entry.getKey();
            int count = entry.getValue();
            
            // 根据重复次数分组
            if (count == 1) cardIndex.singleValues.add(value);
            else if (count == 2) cardIndex.pairValues.add(value);
            else if (count == 3) cardIndex.threeValues.add(value);
            else if (count == 4) cardIndex.fourValues.add(value);
        }
        return cardIndex;
    }

    /**
     * 确定牌型
     * @param size 卡牌数量
     * @param cardIndex 卡牌索引
     * @param values 排序后的数值列表
     * @return 牌型
     */
    private static CardType determineCardType(int size, CardIndex cardIndex, List<Integer> values) {
        // 单张、对子、三张、炸弹
        if (size <= 4) {
            if (size > 0 && values.get(0).equals(values.get(size - 1))) {
                switch (size) {
                    case 1: return CardType.SINGLE;
                    case 2: return CardType.PAIR;
                    case 3: return CardType.THREE;
                    case 4: return CardType.BOMB;
                }
            }
            // 王炸
            if (size == 2 && values.contains(16) && values.contains(17)) 
                return CardType.BOMB;
            
            // 三带一
            if (size == 4 && (values.get(0).equals(values.get(2)) || 
                               values.get(1).equals(values.get(3)))) 
                return CardType.THREE_WITH_ONE;
        }
        
        // 5张以上牌型
        if (size >= 5) {
            // 三带二
            if (size == 5 && cardIndex.threeValues.size() == 1 && 
                cardIndex.pairValues.size() == 1) 
                return CardType.THREE_WITH_TWO;
            
            // 四带二单
            if (size == 6 && cardIndex.fourValues.size() == 1) 
                return CardType.FOUR_WITH_TWO_SINGLE;
            
            // 四带二对
            if (size == 8 && cardIndex.fourValues.size() == 1 && 
                cardIndex.pairValues.size() == 2) 
                return CardType.FOUR_WITH_TWO_PAIRS;
            
            // 顺子（连续5张以上）
            if (isConsecutive(values, 1, size)) 
                return CardType.STRAIGHT;
            
            // 连对（3对以上连续对子）
            if (size % 2 == 0 && size >= 6 && 
                cardIndex.pairValues.size() == size / 2 && 
                isConsecutive(cardIndex.pairValues, 1, size / 2)) 
                return CardType.CONSECUTIVE_PAIRS;
            
            // 飞机（无带牌）
            if (size % 3 == 0 && cardIndex.threeValues.size() == size / 3 && 
                isConsecutive(cardIndex.threeValues, 1, size / 3)) 
                return CardType.AIRPLANE;
            
            // 飞机带单
            if (size % 4 == 0 && cardIndex.threeValues.size() == size / 4 && 
                isConsecutive(cardIndex.threeValues, 1, size / 4)) 
                return CardType.AIRPLANE_WITH_SINGLES;
            
            // 飞机带对
            if (size % 5 == 0 && cardIndex.threeValues.size() == size / 5 && 
                cardIndex.pairValues.size() == size / 5 && 
                isConsecutive(cardIndex.threeValues, 1, size / 5)) 
                return CardType.AIRPLANE_WITH_PAIRS;
        }
        
        return CardType.INVALID;
    }

    /**
     * 检查数值是否连续
     * @param values 排序后的数值列表
     * @param step 步长（1=顺子，2=连对等）
     * @param expectedSize 预期连续数量
     * @return 是否连续
     */
    private static boolean isConsecutive(List<Integer> values, int step, int expectedSize) {
        if (values.size() < expectedSize) return false;
        
        // 对王不参与顺子
        if (values.contains(16) || values.contains(17)) 
            return false;
        
        // 检查连续关系
        for (int i = 0; i < values.size() - 1; i++) {
            if (values.get(i + 1) - values.get(i) != step) 
                return false;
        }
        return true;
    }

    /**
     * 重新定位玩家手牌
     * @param main 游戏主对象
     * @param cards 玩家手牌
     * @param playerIndex 玩家索引 (0=左侧,1=自己,2=右侧)
     */
    public static void repositionHand(GameMain main, List<Card> cards, int playerIndex) {
        Point startPoint = new Point();
        
        // 根据玩家位置确定起始点
        switch (playerIndex) {
            case 0: // 左侧玩家
                startPoint.x = 50;
                startPoint.y = (450 / 2) - (cards.size() + 1) * PLAYER_HAND_SPACING / 2;
                break;
            case 1: // 自己
                startPoint.x = (800 / 2) - (cards.size() + 1) * PLAYER_HAND_OFFSET / 2;
                startPoint.y = 450;
                break;
            case 2: // 右侧玩家
                startPoint.x = 700;
                startPoint.y = (450 / 2) - (cards.size() + 1) * PLAYER_HAND_SPACING / 2;
                break;
        }
        
        // 定位每张卡牌
        for (Card card : cards) {
            card.setLocation(startPoint);
            main.getContainer().setComponentZOrder(card, 0); // 置顶显示
            
            // 更新下一个卡牌位置
            if (playerIndex == 1) {
                startPoint.x += PLAYER_HAND_OFFSET; // 水平排列
            } else {
                startPoint.y += PLAYER_HAND_SPACING; // 垂直排列
            }
        }
    }
}

/**
 * 卡牌索引（按重复次数分组）
 */
class CardIndex {
    List<Integer> singleValues = new ArrayList<>();   // 单张
    List<Integer> pairValues = new ArrayList<>();     // 对子
    List<Integer> threeValues = new ArrayList<>();    // 三张
    List<Integer> fourValues = new ArrayList<>();     // 四张（炸弹）
}